/***************************************************************************************
 The copyright in this software is being made available under the BSD License, included
 below. This software may be subject to other third party rights,including patent rights,
 and no such rights are granted under this license.

 Regents of the Tsinghua University, Peking University, Zhejiang University, HKUST
 Tsinghua University, Peking University, Zhejiang University, HKUST 2011

 Copyright (c) 2011, Regents of the Tsinghua University, Peking University, Zhejiang
 University, HKUST. All Rights Reserved.

 Redistribution and use in source and binary forms, with or without modification, are
 permitted provided that the following conditions are met:
   * Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   * Neither the names of the copyright holders nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 OF SUCH DAMAGE.
***************************************************************************************/


/*!
************************************************************************
*
* \file fast_me.h
*
* \brief
*   Macro definitions and global variables for fast integer pel motion
*   estimation and fractional pel motion estimation
*
* \author
*   Main contributors: (see contributors.h for copyright, address and affiliation details)
*    - Zhibo Chen         <chenzhibo@tsinghua.org.cn>
*    - JianFeng Xu        <fenax@video.mdc.tsinghua.edu.cn>
*    - Wenfang Fu         <fwf@video.mdc.tsinghua.edu.cn>
*    - Xiaozhong Xu      <xxz@video.mdc.tsinghua.edu.cn>
*
* \date
*   2006.1
************************************************************************
*/

#ifndef _FAST_ME_H_
#define _FAST_ME_H_
#include "global.h"

#define MAX_MV_CAND 12
#define EARLY_TERMINATION  if ((min_mcost-pred_SAD)<pred_SAD*betaFourth_2)             \
  goto fourth_2_step;                                             \
  else if((min_mcost-pred_SAD)<pred_SAD*betaFourth_1)           \
  goto fourth_1_step;

#define SEARCH_ONE_PIXEL  if(abs(cand_x - center_x) <=search_range && abs(cand_y - center_y)<= search_range) \
    { \
    if(!McostState[cand_y-center_y+search_range][cand_x-center_x+search_range]) \
    { \
    mcost = MV_COST (lambda_factor, mvshift, cand_x, cand_y, pred_x, pred_y); \
    if(mcost<min_mcost)          \
  {\
  mcost += PartCalMadFME( img->org_y_data, mb_pix_x, mb_pix_y, ref_pic, cand_x, cand_y, blocksize_x, blocksize_y, min_mcost ); \
  McostState[cand_y-center_y+search_range][cand_x-center_x+search_range] = 1; \
  if (mcost < min_mcost) \
    { \
    best_x = cand_x; \
    best_y = cand_y; \
    min_mcost = mcost; \
    } \
  }\
    } \
    }

#define SEARCH_ONE_PIXEL_BIPRED  if(abs(cand_x - s_center_x) <=search_range && abs(cand_y - s_center_y)<= search_range) \
    { \
    if(!McostState[cand_y-s_center_y+search_range][cand_x-s_center_x+search_range]) \
      { \
      target_x[refine_ref_idx] = cand_x;\
      target_y[refine_ref_idx] = cand_y;\
      mcost  = MV_COST(img->lambda_motion_factor, mvshift, target_x[refine_ref_idx], target_y[refine_ref_idx], pred_x, pred_y);\
      mcost  += MV_COST(img->lambda_motion_factor, mvshift, fix_mv->x,    fix_mv->y, pred_fix_mv->x>> mvshift, pred_fix_mv->y>> mvshift );\
      if(mcost<min_mcost)\
        {\
        mcost  += PartCalMadFME_bid(mb_pix_x, mb_pix_y, bi_ref, target_x, target_y, blocksize_x, blocksize_y, refine_ref_idx);\
        McostState[cand_y-s_center_y+search_range][cand_x-s_center_x+search_range] = 1; \
        if (mcost < min_mcost) \
          { \
          best_x = cand_x; \
          best_y = cand_y; \
          min_mcost = mcost; \
          } \
        }\
      } \
    }

byte **McostState;              //state for integer pel search

int ****fastme_ref_cost;                    //store SAD information needed for forward ref-frame prediction
int ***fastme_l0_cost;                      //store SAD information needed for forward median and uplayer prediction
int ***fastme_l1_cost;                      //store SAD information needed for backward median and uplayer prediction
int ***fastme_l0_cost_bipred;               //store SAD information for bipred mode
int ***fastme_l1_cost_bipred;               //store SAD information for bipred mode
int bipred_flag;                            //flag for bipred
int pred_SAD;                // SAD prediction in use.
int pred_MV_ref[2], pred_MV_uplayer[2];     //pred motion vector by space or temporal correlation,Median is provided

int FME_blocktype;              //blocktype for FME SetMotionVectorPredictor
int predict_point[5][2];
int SAD_a,SAD_b,SAD_c,SAD_d;
int Threshold_DSR_MB[6];          // Threshold for usage of DSR. DSR refer to JVT-Q088
//for early termination
float  Bsize[6];
float AlphaFourth_1[6];
float AlphaFourth_2[6];
byte *flag_intra;


int  flag_intra_SAD;

typedef struct
{
    mv_t mvCand[MAX_MV_CAND];
    int  iNum;
} MVPInfo;

typedef struct
{
    macroblock_t *p_MB;

    // neighbor block infomation
    int           block_x;  // in the picture
    int           block_y;  // in the picture
    int           block_x4;  // in 8x8 block
    int           block_y4;  // in 8x8 block

    int        mb_block_x;  // in mb
    int        mb_block_y;  // in mb

    // current block
    int        curr_mb_block_x;
    int        curr_mb_block_y;
} NeighborData;


typedef enum
{
    MB_LEFT,
    MB_TOP,
    MB_ABOVE_RIGHT,
    MB_BELOW_LEFT
} NeighborBlock;


int  deriveMVPandSADFME( MVPInfo* pInfo, int ref_idx, int mb_pix_x, int mb_pix_y, int mode, int list );
void addMVPCandFME( MVPInfo* pInfo, NeighborData *p_Neighbor, int mode, int ref_idx, int list );
int  deriveNeighbors( NeighborData* p_Neighbor, int mb_pix_x, int mb_pix_y, NeighborBlock eBlock );
void addMVPCandTempFME( MVPInfo* pInfo, int mb_pix_x, int mb_pix_y, int ref_idx, int mode, int list );
int  deriveMVPTemp( mv_t *p_mv, int pic_pix_x, int pic_pix_y, int ref_idx, int list );
int  deriveLeft( NeighborData* p_Neighbor, int mb_pix_x, int mb_pix_y );
int  deriveTop ( NeighborData* p_Neighbor, int mb_pix_x, int mb_pix_y );
int  deriveAboveRight( NeighborData* p_Neighbor, int mb_pix_x, int mb_pix_y );
int  deriveBelowLeft ( NeighborData* p_Neighbor, int mb_pix_x, int mb_pix_y );
int  isEqualMV( mv_t *pmv0, mv_t *pmv1 );

void DefineThreshold( void );
void DefineThresholdMB( void );
int get_mem_FME( void );
void free_mem_FME( void );

void decide_intrabk_SAD( void );
void skip_intrabk_SAD( int best_mode, int ref_max );
void setup_FME( short ref, int list, int block_y, int block_x, int blocktype );
int PartCalMadFME_bid( int mb_pix_x, int mb_pix_y, byte ***bi_ref, int *target_x, int *target_y, int blocksize_x, int blocksize_y, int refine_ref_idx );

int                                     //  ==> minimum motion cost after search
FastIntegerPelBlockMotionSearch  (  short     ref,          // <--  reference frame (0... or -1 (backward))
                                    int       list,
                                    int       pic_pix_x,    // <--  absolute x-coordinate of regarded AxB block
                                    int       pic_pix_y,    // <--  absolute y-coordinate of regarded AxB block
                                    int       blocktype,    // <--  block type (1-16x16 ... 7-4x4)
                                    mv_t*     pred_mv,
                                    mv_t*     mv,
                                    int       search_range // <--  1-d search range in pel units
                                 );

int                                                //  ==> minimum motion cost after search
FastBipredIntegerPelBlockMotionSearch (
    int pic_pix_y,
    int pic_pix_x,
    int blocktype,
    mv_t *pred_mv,
    mv_t *pred_fix_mv,
    mv_t* fix_mv,
    mv_t *refine_mv,
    int min_cost
);
int blk4x4_me( int ref_idx, int pic_pix_x, int pic_pix_y, int blocktype,int block_y, int block_x, int blk4x4_y, int blk4x4_x );
int blk4x4_me_bid( int ref_idx, int pic_pix_x, int pic_pix_y, int blocktype,int block_y, int block_x, int blk4x4_y, int blk4x4_x );

#endif
